package common.liusany.admin.service.account;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.liusany.modules.orm.Page;
import com.liusany.modules.orm.PageRequest;
import com.liusany.modules.orm.PropertyFilter;
import common.liusany.admin.dao.account.EmailDao;
import common.liusany.admin.dao.account.GroupDao;
import common.liusany.admin.dao.account.UserDao;
import common.liusany.admin.entity.account.Group;
import common.liusany.admin.entity.account.User;
import common.liusany.admin.service.ServiceException;

/**
 * 安全相关实体的管理类,包括用户和权限组.
 * 
 * @author calvin
 */
// Spring Bean的标识.
@Component
// 默认将类中的所有public函数纳入事务管理.
@Transactional
public class AccountManager {

	private static Logger logger = LoggerFactory
			.getLogger(AccountManager.class);

	private UserDao userDao;
	private GroupDao groupDao;
	private ShiroDbRealm shiroRealm;

	@Resource
	private DataSource dataSource;
	@Resource
	private EmailDao emailDao;
	@Resource
	private MimeMailService mimeMailService;
	
	
	@Transactional
	public void deleteData(){
		emailDao.deleteAll();
	}
	
	// -- User Manager --//
	@Transactional(readOnly = true)
	public User getUser(Long id) {
		return userDao.get(id);
	}

	public void saveUser(User entity) {
		entity.setPassword(org.apache.commons.codec.digest.DigestUtils
				.md5Hex(entity.getPassword()));
		userDao.save(entity);
		shiroRealm.clearCachedAuthorizationInfo(entity.getLoginName());
	}

	/**
	 * 删除用户,如果尝试删除超级管理员将抛出异常.
	 */
	public void deleteUser(Long id) {
		if (isSupervisor(id)) {
			logger.warn("操作员{}尝试删除超级管理员用户", SecurityUtils.getSubject()
					.getPrincipal());
			throw new ServiceException("不能删除超级管理员用户");
		}
		userDao.delete(id);
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	@Transactional(readOnly = true)
	public List<User> getAllUser() {
		System.out.println("getAlluser run...");
		return userDao.getAll("id", true);
	}
	
	public Page<User> findByPage(final PageRequest page, final List<PropertyFilter> filters){
		System.out.println("findByPage run...");
		return userDao.findPage(page, filters);
	}
	
	public void sendEmailFromTxt(File file){
		  try {
				List<String> lines = FileUtils.readLines(file, "UTF-8");
				Integer i = 0;
				
				Long beginTime = System.currentTimeMillis();
				String toMail = "";
				for (String line : lines) {
					if(StringUtils.isNotBlank(line.trim())){
						toMail = line.trim();
						mimeMailService.sendNotificationMail(toMail, "爱状网");
					}
//					if(i>1000){
//						break;
//					}
					i++;
				}
				Thread.sleep(6000);
				logger.info("发送任务已添加到线程池");
				
				Long endTime = System.currentTimeMillis();
		    	System.out.println("pst+batch："+(endTime-beginTime)/1000+"秒");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/**
		 * 读取文件中的50万条数据 高效插入数据库中
		 * @param file
		 */
		public void exec3(File file){ 
	      try {
	          Connection conn = dataSource.getConnection();
	    	  conn.setAutoCommit(false);
	    	  Long beginTime = System.currentTimeMillis();
	    	  PreparedStatement pst = conn.prepareStatement("insert into acct_email(id,email) values (?,?)");
	    	  List<String> lines = FileUtils.readLines(file, "UTF-8");
	    	  Integer i =1;
	    	  for(String line : lines){
	    		  pst.setInt(1, i);
	    		  pst.setString(2, line);
	    		  pst.addBatch();
	    		  if(i%1000==0){
					//可以设置不同的大小；如50，100，500，1000等等
	    			  pst.executeBatch();
	    			  conn.commit();
	    			  pst.clearBatch();
	    		  }
	    		  i++;
	    	  }
	    	  Long endTime = System.currentTimeMillis();
	    	  System.out.println("pst+batch："+(endTime-beginTime)/1000+"秒");
	    	  pst.close();
	    	  conn.close();
	    }catch (SQLException e){
	    	  e.printStackTrace();
	    } catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	   }
		
	/**
	 * 分页查询权限组列表
	 * @param pageRequest
	 * @param filters
	 * @return
	 */
	public Page<Group> findGroupByPage(final PageRequest pageRequest, final List<PropertyFilter> filters){
		return groupDao.findPage(pageRequest, filters);
	}

	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		return userDao.findUniqueBy("loginName", loginName);
	}

	/**
	 * 检查用户名是否唯一.
	 * 
	 * @return newLoginName在数据库中唯一或等于oldLoginName时返回true.
	 */
	@Transactional(readOnly = true)
	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
		return userDao
				.isPropertyUnique("loginName", newLoginName, oldLoginName);
	}

	// -- Group Manager --//
	@Transactional(readOnly = true)
	public Group getGroup(Long id) {
		return groupDao.get(id);
	}

	@Transactional(readOnly = true)
	public List<Group> getAllGroup() {
		return groupDao.getAll("id", true);
	}

	public void saveGroup(Group entity) {
		groupDao.save(entity);
		shiroRealm.clearAllCachedAuthorizationInfo();
	}

//	public void deleteGroup(Long id) {
//		groupDao.delete(id);
//		shiroRealm.clearAllCachedAuthorizationInfo();
//	}

	public void deleteGroup(Long...ids){
		for(Long id : ids){
			groupDao.delete(id);
		}
		shiroRealm.clearAllCachedAuthorizationInfo();
	}
	
	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}

	@Autowired(required = false)
	public void setShiroRealm(ShiroDbRealm shiroRealm) {
		this.shiroRealm = shiroRealm;
	}
}
